package api_test

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"testing"

	"gitee.com/kobeyyf/apibox/api"
	"gitee.com/kobeyyf/apibox/handler"
)

var (
	app   *api.Api
	token string
)

func SetApp(a *api.Api) {
	app = a
}
func SetToken(t string) {
	token = t
}

func GetApp() (*api.Api, error) {
	if app == nil {
		return nil, fmt.Errorf("need init app")
	}

	return app, nil

}

func GetBaseParams() url.Values {
	params := make(url.Values)
	params.Add("AppCode", app.Config.GetString("app.code"))
	return params
}

func ParseResponse(r io.Reader) *handler.Response {
	buf, err := ioutil.ReadAll(r)
	if err != nil {
		return nil
	}
	resp := new(handler.Response)
	fmt.Println(string(buf))
	json.Unmarshal(buf, resp)
	return resp
}

func ActionByGet(params url.Values) *handler.Response {
	target := app.Config.GetString("server.pattern") + "?" + params.Encode()
	r := httptest.NewRequest(http.MethodGet, target, nil)
	w := httptest.NewRecorder()
	app.Test(w, r)

	return ParseResponse(w.Body)
}

func ActionByPost(params url.Values) *handler.Response {
	body := bytes.NewBufferString(params.Encode())
	target := app.Config.GetString("server.pattern") + "?"
	r := httptest.NewRequest(http.MethodPost, target, body)
	r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	r.Header.Set("Token", token)
	fmt.Println(r.Header)
	w := httptest.NewRecorder()
	app.Test(w, r)
	fmt.Println("request params ")
	fmt.Println(params.Encode())
	fmt.Println(w.Header())
	return ParseResponse(w.Body)
}

func ActionByPostForm(params url.Values, formData url.Values) *handler.Response {
	body := bytes.NewBuffer(nil)
	target := app.Config.GetString("server.pattern") + "?" + params.Encode()
	mult := multipart.NewWriter(body)
	for k, v := range formData {
		for _, sv := range v {
			mult.WriteField(k, sv)
		}
	}
	mult.Close()
	r := httptest.NewRequest(http.MethodPost, target, body)
	r.Header.Set("Content-Type", "multipart/form-data; boundary="+mult.Boundary())
	w := httptest.NewRecorder()
	app.Test(w, r)
	return ParseResponse(w.Body)
}

func ActionByPostFile(params url.Values, fd *os.File) *handler.Response {
	body := bytes.NewBuffer(nil)
	target := app.Config.GetString("server.pattern") + "?" + params.Encode()
	mult := multipart.NewWriter(body)
	fiw, err := mult.CreateFormFile("file", fd.Name())
	if err != nil {

		fmt.Println(err)
		return nil
	}
	io.Copy(fiw, fd)
	mult.Close()
	r := httptest.NewRequest(http.MethodPost, target, body)
	r.Header.Set("Content-Type", "multipart/form-data; boundary="+mult.Boundary())
	w := httptest.NewRecorder()
	app.Test(w, r)
	return ParseResponse(w.Body)
}

func WantResp(resp *handler.Response, want *handler.Response, t *testing.T) {
	if resp == nil {
		t.Error("get nil resp")
		t.FailNow()
	}

	if resp.Code != want.Code {
		t.Errorf("not want code %s, but get %s", want.Code, resp.Code)
		t.Error(resp.Message)
		t.FailNow()
	}

}

func WantOKResp(resp *handler.Response, t *testing.T) {
	if resp == nil {
		t.Error("get nil resp")
		t.FailNow()
	}

	if resp.Code != handler.STATUS_OK {
		t.Error("get failed code", resp.Code)
		t.Error(resp)
		t.FailNow()

	}
}

func WantErrResp(resp *handler.Response, t *testing.T) {
	if resp == nil {
		t.Error("get nil resp")
		t.FailNow()
	}

	if resp.Code == handler.STATUS_OK {
		t.Error("want error resp , but get ok resp")
		t.Error(resp)
		t.FailNow()
	}
}
